package cn.digitalgd.directoryTree.service.impl;

import cn.digitalgd.directoryTree.mapper.DirectoryMapper;
import cn.digitalgd.directoryTree.pojo.dto.PageDTO;
import cn.digitalgd.directoryTree.pojo.po.DirectoryPO;
import cn.digitalgd.directoryTree.pojo.vo.DirectoryVO;
import cn.digitalgd.directoryTree.pojo.vo.PageVO;
import cn.digitalgd.directoryTree.service.IDirectoryService;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ Author：浅汐
 * @ Date：2024/7/16
 * @ Desc：
 */
@Service
public class DirectoryServiceImpl extends ServiceImpl<DirectoryMapper, DirectoryPO> implements IDirectoryService {
    @Resource
    private DirectoryMapper directoryMapper;

    @Override
    public void createANewNode(DirectoryVO directoryVO) {
        Integer level = 1;
        Integer parentId = 0;
        if (directoryVO.getParentId() != null) {
//            Integer parentLevel = directoryMapper.getParentLevel(directoryVO);
            DirectoryPO directoryPO = directoryMapper.selectOne(Wrappers.lambdaQuery(DirectoryPO.class)
                    .eq(DirectoryPO::getId, directoryVO.getParentId()));
            Integer parentLevel= directoryPO.getLevel();

            if (parentLevel >= 3) throw new IllegalArgumentException("目录层级不能超过3层");
            level = parentLevel + 1;
            parentId = directoryVO.getParentId();
        }

//        Integer sort = directoryMapper.getSort(parentId) + 1;
        Long sort = directoryMapper.selectCount(Wrappers.lambdaQuery(DirectoryPO.class).eq(DirectoryPO::getParentId, parentId));
        DirectoryPO directoryPO = DirectoryPO.builder()
                .level(level)
                .sort(sort)
                .name(directoryVO.getName())
                .parentId(directoryVO.getParentId())
                .build();
        save(directoryPO);
    }

    @Override
    public void updateANode(DirectoryVO directoryVO) {
        Integer level = 1;
        Integer parentId = 0;
        if (directoryVO.getParentId() != null) {
            DirectoryPO directoryPO = directoryMapper.selectOne(Wrappers.lambdaQuery(DirectoryPO.class)
                    .eq(DirectoryPO::getId, directoryVO.getParentId()));
            Integer parentLevel= directoryPO.getLevel();
            if (parentLevel >= 3) throw new IllegalArgumentException("目录层级不能超过3层");
            level = parentLevel + 1;
            parentId = directoryVO.getParentId();
        }
//        Integer sort = directoryMapper.getSort(parentId) + 1;
        Long sort = directoryMapper.selectCount(Wrappers.lambdaQuery(DirectoryPO.class).eq(DirectoryPO::getParentId, parentId));
        DirectoryPO directoryPo = DirectoryPO.builder()
                .level(level)
                .sort(sort)
                .name(directoryVO.getName())
                .parentId(directoryVO.getParentId())
                .id(directoryVO.getId())
                .build();
        updateById(directoryPo);
    }

    @Override
    public void upANode(Long id) {
        DirectoryPO directoryPO = getOne(Wrappers.lambdaQuery(DirectoryPO.class).eq(DirectoryPO::getId, id));
        if (directoryPO.getSort() == 1) throw new IllegalArgumentException("已经是第一个节点");
        DirectoryPO directoryPOBefore = getOne(Wrappers.lambdaUpdate(DirectoryPO.class)
                .eq(DirectoryPO::getSort, directoryPO.getSort() - 1)
                .eq(DirectoryPO::getParentId, directoryPO.getParentId()));
        lambdaUpdate().eq(DirectoryPO::getId, directoryPO.getId()).set(DirectoryPO::getSort, directoryPO.getSort() - 1).update();
        lambdaUpdate().eq(DirectoryPO::getId, directoryPOBefore.getId()).set(DirectoryPO::getSort, directoryPOBefore.getSort() + 1).update();

    }

    @Override
    public void downANode(Long id) {
        DirectoryPO directoryPO = getOne(Wrappers.lambdaQuery(DirectoryPO.class).eq(DirectoryPO::getId, id));
        if (directoryPO.getSort() == directoryMapper.selectCount(Wrappers.lambdaQuery(DirectoryPO.class).eq(DirectoryPO::getParentId, directoryPO.getParentId()))) {
            throw new IllegalArgumentException("已经是最后一个个节点");
        }
        DirectoryPO directoryPOAfter = getOne(Wrappers.lambdaUpdate(DirectoryPO.class)
                .eq(DirectoryPO::getSort, directoryPO.getSort() + 1)
                .eq(DirectoryPO::getParentId, directoryPO.getParentId()));
        lambdaUpdate().eq(DirectoryPO::getId, directoryPO.getId()).set(DirectoryPO::getSort, directoryPO.getSort() + 1).update();
        lambdaUpdate().eq(DirectoryPO::getId, directoryPOAfter.getId()).set(DirectoryPO::getSort, directoryPOAfter.getSort() - 1).update();

    }


    @Override
    public PageDTO<DirectoryPO> pageTree(PageVO pageVO) {
        Page<DirectoryPO> page = Page.of(pageVO.getPageNum(), pageVO.getPageSize());
//        page.addOrder(new OrderItem("sort", true));
//        Page<DirectoryPO> directoryPOPage = page(page);
        Page<DirectoryPO> directoryPOPage = directoryMapper.selectPage(page, Wrappers.lambdaQuery(DirectoryPO.class).orderByAsc(DirectoryPO::getSort));
        List<DirectoryPO> records = directoryPOPage.getRecords();
        List<DirectoryPO> result = records.stream()
                .filter(directoryPO -> 0 == directoryPO.getParentId())
                .peek(directoryPO -> directoryPO.setChild(createChildList(directoryPO, records)))
                .collect(Collectors.toList());
        PageDTO<DirectoryPO> pageDTO=new PageDTO();
        pageDTO.setList(result);
        pageDTO.setPages(directoryPOPage.getPages());
        pageDTO.setTotal(directoryPOPage.getTotal());
        return pageDTO;
    }

    /**
     * @param directoryPO  父级
     * @param directoryPOList 对应的list
     * @return
     */
    private static List<DirectoryPO> createChildList(DirectoryPO directoryPO, List<DirectoryPO> directoryPOList) {

        return directoryPOList.stream()
                .filter(model -> directoryPO.getId().equals(model.getParentId()))
                .peek(model -> model.setChild(createChildList(model, directoryPOList)))
                .collect(Collectors.toList());
    }

}
